package com.sdlh.demo.springboot.common.mqtt;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

/**
 * 常规MQTT回调函数
 * MqttCallback 接口定义了用于处理 MQTT 客户端异步事件的方法。
 * 当使用 Eclipse Paho MQTT 客户端库时，你可以实现这个接口来接收连接状态的变化和消息传递的通知。
 */
@Slf4j
public class Callback implements MqttCallback {

    /**
     * MQTT 断开连接会执行此方法
     *
     * 方法说明：当客户端与 MQTT 服务器之间的连接丢失时，此方法被调用。
     * @param throwable 表示导致连接丢失的原因，通常为一个 Throwable 对象
     */
    @Override
    public void connectionLost(Throwable throwable) {
        log.info("断开了MQTT连接 ：{}", throwable.getMessage());
        log.error(throwable.getMessage(), throwable);
    }

    /**
     * publish发布成功后会执行到这里
     *
     * 方法说明：当一个消息的交付完成并且所有必要的确认都已收到时，此方法被调用。
     * 注意事项：
     * 对于 QoS 0 消息，在消息被网络层接收后会调用此方法。
     * 对于 QoS 1 消息，在接收到 PUBACK 包后调用此方法。
     * 对于 QoS 2 消息，在接收到 PUBCOMP 包后调用此方法。
     * @param iMqttDeliveryToken the delivery token associated with the message.
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        try {
            log.info("-------发布消息成功: "+new String(iMqttDeliveryToken.getMessage().getPayload())+"-------");
        } catch (MqttException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * subscribe订阅后得到的消息会执行到这里
     *
     * 方法说明：当从服务器接收到一条新消息时，此方法被调用
     * 注意事项：
     * 在此方法中抛出任何异常将会导致客户端关闭，并且未确认的消息可能会被重新发送。
     * 如果在此方法执行期间有其他消息到达，它们将被缓存直到此方法返回。
     * @param topic 消息发布的主题名称
     * @param message 实际的消息内容，类型为 MqttMessage
     * @throws Exception
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        //  TODO    此处可以将订阅得到的消息进行业务处理、数据存储
        log.info("收到来自主题 " + topic + " 的消息：{}", new String(message.getPayload()));
    }
}
